#include "stdafx.h"
#include "TBSCertificateGenerator.h"
#include "Name.h"
#include "ASN1Null.h"

namespace AC = AppliedCryptography;

namespace AppliedCryptography
{
	TBSCertificateGenerator::TBSCertificateGenerator(
			TBSVersion* version,
			ASN1Integer* serialNumber,
			ASN1ObjectIdentifier* signAlgoOID,
			Name* issuer,
			ASN1UTCTime* startDate,
			ASN1UTCTime* endDate,
			Name* subject,
			ASN1Encoded* publicKey,
			Extensions* extensions)
		: _version(version),
		_serialNumber(serialNumber),
		_signatureAlgorithm(signAlgoOID),
		_issuer(issuer),
		_startDate(startDate),
		_endDate(endDate),
		_subject(subject),
		_publicKey(publicKey),
		_extensions(extensions)
	{
		_version->set(TBSVersion::v3);
	};

	/*
	TBSCertificateGenerator::TBSCertificateGenerator()
		: _version(new TBSVersion()),
		_serialNumber(new ASN1Integer()),
		_signatureAlgorithm(new ASN1ObjectIdentifier()),
		_issuer(new Name()),
		_startDate(new ASN1UTCTime()),
		_endDate(new ASN1UTCTime()),
		_subject(new Name()),
		_publicKey(new ASN1BitString())
	{
		_version->set(TBSVersion::v3);
	};
	*/

	TBSCertificateGenerator::~TBSCertificateGenerator()
	{
		delete _version;
		delete _serialNumber;
		delete _signatureAlgorithm;
		delete _issuer;
		delete _startDate;
		delete _endDate;
		delete _subject;
		delete _extensions;
	};

	TBSCertificateGenerator& TBSCertificateGenerator::setSerialNumber(unsigned long serialNumber)
	{
		*_serialNumber = serialNumber;
		return *this;
	};

	TBSCertificateGenerator& TBSCertificateGenerator::setIssuer(Name& issuer)
	{
		*_issuer = issuer;
		return *this;
	};

	TBSCertificateGenerator& TBSCertificateGenerator::setSubject(Name& subject)
	{
		*_subject = subject;
		return *this;
	};

	TBSCertificateGenerator& TBSCertificateGenerator::setStartDate(ASN1UTCTime& startDate)
	{
		*_startDate = startDate;
		return *this;
	};

	TBSCertificateGenerator& TBSCertificateGenerator::setEndDate(ASN1UTCTime& endDate)
	{
		*_endDate = endDate;
		return *this;
	};

	TBSCertificateGenerator& TBSCertificateGenerator::setPublicKey(ASN1Encoded& key)
	{
		*_publicKey = key;
		return *this;
	};

	TBSCertificateGenerator& TBSCertificateGenerator::setExtensions(Extensions& extensions)
	{
		*_extensions = extensions;
		return *this;
	};

	ASN1Sequence& TBSCertificateGenerator::add(ASN1Encodable& obj)
	{
		this->ASN1Sequence::add(obj);
		return *this;
	};

	ASN1Encodable& TBSCertificateGenerator::get(unsigned int index) const
	{
		return this->ASN1Sequence::get(index);
	};

	unsigned int TBSCertificateGenerator::size() const
	{
		return -1;
	};

	std::vector<byte> TBSCertificateGenerator::getContentBits() const
	{
		ASN1Sequence cert;
		ASN1Sequence validity;
		ASN1Sequence signature; // AlgorithmIdentifier
		ASN1Sequence crypto, cryptoAlgorithm; //AlgorithmIdentifier
		ASN1Null null;

		signature.add(*_signatureAlgorithm);
		signature.add(null);

		validity.add(*_startDate);
		validity.add(*_endDate);

		cryptoAlgorithm.add(*_signatureAlgorithm);
		cryptoAlgorithm.add(null);
		crypto.add(cryptoAlgorithm);
		crypto.add(*_publicKey);

		cert.add(*_version);
		cert.add(*_serialNumber);
		cert.add(signature);
		cert.add(*_issuer);
		cert.add(validity);
		cert.add(*_subject);
		//cert.add(crypto);
		cert.add(*_publicKey);

		if(_extensions->size() > 0)
			cert.add(*_extensions);

		return cert.getContentBits();
	};

	TBSCertificateGenerator& TBSCertificateGenerator::setSignatureAlgorithm(AC::ASN1ObjectIdentifier& algorithm)
	{
		*_signatureAlgorithm = algorithm;
		return *this;
	};
}; // namespace AppliedCryptography
